package com.programmingteam.wallpaperslideshow.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Log;

import com.programmingteam.wallpaperslideshow.Config;

public class ImageOperations {
	private static final String TAG = "WallpaperSlideshow";

//	public boolean generateThumbnail(File source, File target) {
//		boolean isOperationOk = false;
//		BitmapFactory.Options o;
//		int width, height, newWidth, newHeight;
//
//		System.gc();
//		try {
//			o = new BitmapFactory.Options();
//			o.inJustDecodeBounds = true;
//			BitmapFactory.decodeStream(new FileInputStream(source), null, o);
//			width = o.outWidth;
//			height = o.outHeight;
//			newWidth = Config.ImageSize.THUMBNAIL_WIDTH;
//			newHeight = (newWidth * height) / width;
//
//			if (newWidth > width && newHeight > height) {
//				isOperationOk = copyImg(source, target);
//			}
//			else {
//				isOperationOk = copyAndResizeToThumb(source, target);
//			}
//		}
//		catch (FileNotFoundException e) {
//			e.printStackTrace();
//		}
//		return isOperationOk;
//	}

	public boolean copyImg(File source, File target) {

		boolean isOperationOk = false;
		FileChannel src, dst;
		try {
			src = new FileInputStream(source).getChannel();
			dst = new FileOutputStream(target).getChannel();
			dst.transferFrom(src, 0, src.size());
			src.close();
			dst.close();
			System.gc();
			isOperationOk = true;
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return isOperationOk;
	}

//	public boolean copyAndResizeToThumb(File source, File target) {
//
//		boolean isOperationOk = false;
//		Bitmap bitmapOrg = null, resizedBitmap;
//		BitmapFactory.Options opts;
//		FileOutputStream out;
//		Matrix matrix;
//		int downsample = 1, width, height, newWidth, newHeight;
//		float scaleWidth, scaleHeight;
//
//		// Make sure that bitmap is not too big
//		while (bitmapOrg == null) {
//			try {
//				System.gc();
//				opts = new BitmapFactory.Options();
//				opts.inSampleSize = downsample;
//				bitmapOrg = BitmapFactory.decodeStream(new FileInputStream(source), null, opts);
//			}
//			catch (OutOfMemoryError ome) {
//				downsample = downsample * 2;
//				Log.d(TAG, "Not enaugh memory, downsampling: " + downsample);
//			}
//			catch (FileNotFoundException e) {
//				e.printStackTrace();
//			}
//		}
//
//		width = bitmapOrg.getWidth();
//		height = bitmapOrg.getHeight();
//		newWidth = Config.ImageSize.THUMBNAIL_WIDTH;
//		newHeight = (newWidth * height) / width;
//
//		scaleWidth = ((float) newWidth) / width;
//		scaleHeight = ((float) newHeight) / height;
//
//		if (scaleWidth > 1 && scaleHeight > 1) {
//			scaleWidth = scaleHeight = 1;
//		}
//
//		matrix = new Matrix();
//		matrix.postScale(scaleWidth, scaleHeight);
//
//		// recreate the new Bitmap
//		System.gc();
//		resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true);
//
//		bitmapOrg = null;
//		System.gc();
//
//		try {
//			out = new FileOutputStream(target);
//			resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
//			out.flush();
//			out.close();
//			out = null;
//			resizedBitmap = null;
//			System.gc();
//			isOperationOk = true;
//		}
//		catch (Exception e) {
//			e.printStackTrace();
//		}
//		return isOperationOk;
//	}

	/**
	 * Resize image with crop option and file overwrite
	 * @param imageFile image file to be overwritten
	 * @param height Desired height
	 * @param width Desired width
	 * @return flag indicating whether operation was successful
	 * @throws IOException 
	 */
	public boolean resizeImage(File imageFile, int height, int width)
			throws FileNotFoundException, IOException {
		return resizeImage(imageFile, imageFile, height, width);
	}

	/** 
	 * Resize image with crop option
	 * @param inputImage File containing input image
	 * @param outputImage File containing output image
	 * @param wpHeight Desired height
	 * @param wpWidth Desired widths
	 * @return flag indicating whether operation was successful
	 * @throws IOException 
	 */
	public boolean resizeImage(File inputImage, File outputImage, int wpHeight, int wpWidth)
			throws FileNotFoundException, IOException {
		boolean isOperationOk = false;
		int downsample = 1, width, height, x, y, outWidth, outHeight;
		float imgRatio, wpRatio;
		Bitmap inBitmap = null, resizedBitmap;
		BitmapFactory.Options opts;
		FileOutputStream out;
		Matrix matrix;

		opts = new BitmapFactory.Options();
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(new FileInputStream(inputImage), null, opts);

		outWidth = width = opts.outWidth;
		outHeight = height = opts.outHeight;

		if (wpHeight == height && wpWidth == width) { return true; }

		while ((long) outWidth * outHeight > Config.ImageSize.DOWNSAMPLE_TRESHOLD) {
			downsample *= 2;
			outWidth = width / downsample;
			outHeight = height / downsample;
		}

		Log.d(TAG, "<IMGOPS> Downsample: " + downsample);

		opts = new BitmapFactory.Options();
		opts.inSampleSize = downsample;
		inBitmap = BitmapFactory.decodeStream(new FileInputStream(inputImage), null, opts);
		matrix = new Matrix();

		Log.d(TAG, "<IMGOPS> Resize");

		// Q's hack - do not resize on invalid size
		if (wpHeight < 0 || wpWidth < 0) {
			outWidth = width;
			outHeight = height;
			x = 0;
			y = 0;
		}
		else {
			width = inBitmap.getWidth();
			height = inBitmap.getHeight();

			imgRatio = ((float) width) / height;
			wpRatio = ((float) wpWidth) / wpHeight;

			if (wpRatio < imgRatio) {
				x = (int) ((width - (height * wpRatio)) / 2);
				y = 0;
				outWidth = (int) (height * wpRatio);
				outHeight = height;
			}
			else {
				x = 0;
				y = (int) ((height - (width / wpRatio)) / 2);
				outWidth = width;
				outHeight = (int) (width / wpRatio);
			}

			float scaleWidth = ((float) wpWidth) / outWidth;
			float scaleHeight = ((float) wpHeight) / outHeight;
			matrix.postScale(scaleWidth, scaleHeight);
		}

		Log.d(TAG, "<IMGOPS> Create resized");

		// recreate the new Bitmap
		System.gc();
		resizedBitmap = Bitmap.createBitmap(inBitmap, x, y, outWidth, outHeight, matrix, true);

		inBitmap = null;
		System.gc();

		out = new FileOutputStream(outputImage);
		resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
		out.flush();
		out.close();

		out = null;
		resizedBitmap.recycle();
		resizedBitmap = null;
		isOperationOk = true;
		System.gc();

		Log.d(TAG, "<IMGOPS> Done");

		return isOperationOk;
	}
}
